/**
 */
package fUML.Semantics.Classes.Kernel;

import fUML.Semantics.Loci.LociL1.SemanticVisitor;

import fUML.Syntax.Classes.Kernel.Classifier;
import fUML.Syntax.Classes.Kernel.ValueSpecification;

import org.eclipse.emf.common.util.EList;

/**
 * <!-- begin-user-doc -->
 * A representation of the model object '<em><b>Value</b></em>'.
 * <!-- end-user-doc -->
 *
 * <!-- begin-model-doc -->
 * A value is an instance of one or more classifiers, which are its types. A value
 *                 is always representable using a value specification.
 *  
 *  [Note: Value
 *                 specializes SemanticVisitor to allow the Execution subclass to be a semantic
 *                 visitor, without requiring multiple generalization of Execution.]
 * <!-- end-model-doc -->
 *
 *
 * @see fUML.Semantics.Classes.Kernel.KernelPackage#getValue()
 * @model abstract="true"
 * @generated
 */
public interface Value extends SemanticVisitor {
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * Return a value specification whose evaluation gives a value equal to this
	 *                   value.
	 *  
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false"
	 * @generated
	 */
	ValueSpecification specify();

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Test if this value is equal to otherValue. To be equal, this value must
	 *                   have the same type as otherValue. 
	 *  // This operation must be overridden
	 *                   in Value subclasses to check for equality of properties defined in those
	 *                   subclasses.
	 *  
	 *  ClassifierList myTypes = this.getTypes();
	 *                   ClassifierList otherTypes = otherValue.getTypes();
	 *  
	 *  boolean
	 *                   isEqual = true;
	 *  
	 *  // Debug.println("[equals] Value...");
	 *                   // Debug.println("[equals] this has " + myTypes.size() + "types, other has " +
	 *                   otherTypes.size() + ".");
	 *  if (myTypes.size() != otherTypes.size())
	 *                   {
	 *  isEqual = false;
	 *  
	 *  } else {
	 *  //
	 *                   Debug.println("[equals] " + myTypes.size() + " type(s).");
	 *  
	 *  int
	 *                   i = 1;
	 *  while (isEqual & i <= myTypes.size()) {
	 *                   
	 *  // Debug.println("[equals] this type = " +
	 *                   myTypes.getValue(i-1).name);
	 *  
	 *  boolean matched = false;
	 *                   int j = 1;
	 *  while (!matched & j <= otherTypes.size())
	 *                   {
	 *  // Debug.println("[equals] other type = " +
	 *                   otherTypes.getValue(j-1).name);
	 *  matched = (otherTypes.getValue(j-1) ==
	 *                   myTypes.getValue(i-1));
	 *  j = j + 1;
	 *  }
	 *  
	 *  isEqual
	 *                   = matched;
	 *  i = i + 1;
	 *  }
	 *  }
	 *  
	 *  return
	 *                   isEqual;
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false" otherValueRequired="true" otherValueOrdered="false"
	 * @generated
	 */
	boolean equals(Value otherValue);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Create a new value that is equal to this value. 
	 *  // By default,
	 *                   this operation simply creates a new value with empty properties. 
	 *  // It
	 *                   must be overridden in each Value subclass to do the superclass copy and then
	 *                   appropriately set properties defined in the subclass.
	 *  
	 *  return
	 *                   this.new_();
	 *  
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false"
	 * @generated
	 */
	Value copy();

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * Create a new value of the same Value subclass as this value, with all
	 *                   properties empty (even if this violates multiplicity constraints). 
	 *  This
	 *                   operation must be defined in each concrete Value subclass to create an instance of
	 *                   that subclass.
	 *  
	 *  
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false"
	 * @generated
	 */
	Value new_();

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * Gets all the classifiers under which this value is currently
	 *                   classifier.
	 *  
	 * <!-- end-model-doc -->
	 * @model kind="operation" ordered="false"
	 * @generated
	 */
	EList<Classifier> getTypes();

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Check if this object has the given classifier as a type.
	 *  
	 *                   ClassifierList types = this.getTypes();
	 *  
	 *  boolean found =
	 *                   false;
	 *  int i = 1;
	 *  while (!found & i <=
	 *                   types.size()) {
	 *  found = (types.getValue(i-1) == type);
	 *  i = i +
	 *                   1;
	 *  }
	 *  
	 *  return found;
	 *  
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false" typeRequired="true" typeOrdered="false"
	 * @generated
	 */
	boolean hasType(Classifier type);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * Return a string representation of this value.
	 *  
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false"
	 * @generated
	 */
	String toString();

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Return an identifier for this object.
	 *  // [Non-normative.]
	 *                   
	 *  return super.toString();
	 *  
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false"
	 * @generated
	 */
	String objectId();

} // Value
